package edu.unicen.activateServices.service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;

import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.Settings;
import android.util.Log;
import edu.unicen.activateServices.activity.AndroidActivateServicesActivity;
import edu.unicen.activateServices.activity.R;
import edu.unicen.activateServices.model.Rule;

/**
 * @author <li>diegopiu</li> <li>silvinawesner</li>
 */
public class AndroidActivateServicesService extends Service {

	private static final String TAG = "AndroidActivateServicesService";

	private ActivityManager activityManager;

	private Receiver receiver = new Receiver();

	private final IBinder mBinder = new LocalBinder();

	private volatile PollingThread pollingThread;

	private Intent intent;

	@Override
	public IBinder onBind(Intent intent) {
		Log.d(TAG, "onBind");
		this.intent = intent;
		registerReceiver(receiver, new IntentFilter(Intent.ACTION_SCREEN_ON));
		registerReceiver(receiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
		startPollingThread();
		return mBinder;
	}

	@Override
	public void onCreate() {
		Log.d(TAG, "onCreate");
		this.activityManager = (ActivityManager) this
				.getSystemService(ACTIVITY_SERVICE);
		super.onCreate();
	}

	@Override
	public void onDestroy() {
		Log.d(TAG, "onDestroy");
		unregisterReceiver(receiver);
		stopPollingThread();
		super.onDestroy();
	}

	private synchronized void startPollingThread() {
		if (pollingThread == null) {
			pollingThread = new PollingThread(intent.getExtras());
			Log.d(TAG, "startPollingThread");
			pollingThread.start();
		}
	}

	private synchronized void stopPollingThread() {
		if (pollingThread != null) {
			Log.d(TAG, "stopPollingThread");
			pollingThread.requestStop();
			pollingThread = null;
		}
	}

	private void activateServices(Bundle bundle) {
		Boolean activatedWifi = false;
		Boolean activatedGps = false;
		Boolean notify = false;
		List<RunningTaskInfo> runningTasks = activityManager
				.getRunningTasks(bundle
						.getInt(AndroidActivateServicesActivity.WINDOW_KEY));

		HashMap<String, Rule> rules = AndroidActivateServicesActivity
				.stringToRules(bundle
						.getString(AndroidActivateServicesActivity.RULES));

		for (RunningTaskInfo runningTaskInfo : runningTasks) {
			Log.d(TAG, runningTaskInfo.baseActivity.getPackageName());

			if (rules
					.containsKey(runningTaskInfo.baseActivity.getPackageName())) {

				Rule rule = rules.get(runningTaskInfo.baseActivity
						.getPackageName());
				if (rule.requireWifi()) {
					WifiManager wifiManager = (WifiManager) getBaseContext()
							.getSystemService(Context.WIFI_SERVICE);
					if (!wifiManager.isWifiEnabled()) {
						// Habilito el WIFI
						wifiManager.setWifiEnabled(true);
						activatedWifi = true;
					}
				}
				if (rule.requireGps()) {
					String provider = Settings.Secure.getString(
							getContentResolver(),
							Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
					if (!provider.contains("gps")) { // Si el GPS está
														// desabilitado
						final Intent intentGPS = new Intent();
						intentGPS
								.setClassName("com.android.settings",
										"com.android.settings.widget.SettingsAppWidgetProvider");
						intentGPS.addCategory(Intent.CATEGORY_ALTERNATIVE);
						intentGPS.setData(Uri.parse("3"));
						sendBroadcast(intentGPS);
						activatedGps = true;
					}

				}
			}
			// Logeo un mensaje en la barra de notificaciones
			String ns = Context.NOTIFICATION_SERVICE;
			NotificationManager notificationManager = (NotificationManager) getSystemService(ns);
			Notification notification = new Notification(
					R.drawable.logo, "Servicio activado",
					System.currentTimeMillis());
			notification.flags = Notification.FLAG_AUTO_CANCEL;
			CharSequence contentText = "";
			if ((activatedWifi) && (activatedGps)) {
				contentText = "Se activó el WIFI y el GPS";
				notify = true;
			} else if (activatedWifi) {
				contentText = "Se activó el WIFI";
				notify = true;
			} else if (activatedGps) {
				contentText = "Se activó el GPS";
				notify = true;
			}
			if (notify) {
				Context context = getApplicationContext();
				CharSequence contentTitle = "AndroidActivateServices";
				Intent notificationIntent = new Intent(this,
						AndroidActivateServicesService.class);
				PendingIntent contentIntent = PendingIntent.getActivity(this,
						0, notificationIntent, 0);
				notification.setLatestEventInfo(context, contentTitle,
						contentText, contentIntent);
				notificationManager.notify(1, notification);
			}
		}
	}

	public void setIntent(Intent intent) {
		this.intent = intent;
		stopPollingThread();
		startPollingThread();
	}

	/**
	 * Clase usada por el cliente Binder. El servicio siempre se ejecuta en el
	 * mismo proceso que su cliente.
	 */
	public class LocalBinder extends Binder {
		public AndroidActivateServicesService getService() {
			return AndroidActivateServicesService.this;
		}

	}

	/**
	 * Thread que se encarga de ejecutar una acción y esperar un período de
	 * tiempo (polling).
	 */
	public class PollingThread extends Thread {

		private static final String TAG = "PollingThread";
		private volatile boolean stop = false;
		private Bundle bundle;

		public PollingThread(Bundle bundle) {
			super();
			this.bundle = bundle;
		}

		public void run() {
			while (!stop) {
				Log.d(TAG,
						"run "
								+ new Date(System.currentTimeMillis())
										.toLocaleString());
				try {
					activateServices(bundle);
					Thread.sleep(bundle
							.getInt(AndroidActivateServicesActivity.POLLING_TIME_KEY) * 1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}

		public synchronized void requestStop() {
			stop = true;
		}
	}

	/**
	 * Clase que contiene el código para manejar los intents, particularmente
	 * cuando se apaga o enciende la pantalla.
	 */
	public class Receiver extends BroadcastReceiver {
		private static final String TAG = "Receiver";

		@Override
		public void onReceive(Context context, Intent intent) {
			if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
				Log.d(TAG, "Intent.ACTION_SCREEN_OFF");
				stopPollingThread();
			} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
				Log.d(TAG, "Intent.ACTION_SCREEN_ON");
				startPollingThread();
			}
		}
	}
}
